﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for AccountSelector.xaml
    /// </summary>
    public partial class AccountSelector : UserControl
    {
        public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(AccountSelector), new UIPropertyMetadata(null, OnItemsSourceChangedHandler));
        public static readonly DependencyProperty DisplayMemberPathProperty = DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(AccountSelector), new UIPropertyMetadata(null, OnDisplayMemberPathChangedHandler));

        private static void OnDisplayMemberPathChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            AccountSelector that = sender as AccountSelector;
            that.tvData.DisplayMemberPath = e.NewValue as string;
        }

        private static void OnItemsSourceChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            AccountSelector that = sender as AccountSelector;
            that.tvData.ItemsSource = e.NewValue as IEnumerable;
        }

        public IEnumerable ItemsSource
        {
            get { return GetValue(ItemsSourceProperty) as IEnumerable; }
            set { SetValue(ItemsSourceProperty, this); }
        }

        public string DisplayMemberPath
        {
            get { return GetValue(DisplayMemberPathProperty) as string; }
            set { SetValue(DisplayMemberPathProperty, value); }
        }

        public AccountSelector()
        {
            InitializeComponent();
        }

        TreeViewItem tv;
        bool IsTextboxFocus = false;
        bool selectedText;
        object SelectedClass;
        object selectedTV;
        long LastTicks;
        #region TreeView Events

        private void tvData_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (tvData.SelectedItem != null)
            {
                if (tvData.SelectedItem.GetType().ToString() == "TanmiaGrp.GeneralLedger.Core.Account")
                {
                    tv = tvData.ContainerFromItem(tvData.SelectedItem);
                    if (IsTextboxFocus == false)
                    {
                        txtCity.Text = GetDisplyString(tvData.SelectedItem);// ((HierarchicalCity)tvData.SelectedItem).CityName;
                        selectedText = true;
                    }
                    SelectedClass = tvData.SelectedItem;// (HierarchicalCity)tvData.SelectedItem;
                }
                else if (tvData.SelectedItem.GetType().ToString() == "AutoCompleteTextBox.SilverlightTreeViewItem")
                {
                    tv = (TreeViewItem)tvData.SelectedItem;
                }
            }
        }

        private void tvData_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape || e.Key == Key.Enter)
            {
                if (e.Key == Key.Enter && SelectedClass != null)
                {
                    txtCity.Text = GetDisplyString(SelectedClass);/// SelectedClass.CityName;
                    selectedText = true;
                }
                txtCity.Focus();
                HideTreeview();
            }
        }

        private void tvData_GotFocus(object sender, RoutedEventArgs e)
        {
            GoToItem();
        }

        private void tvData_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if ((DateTime.Now.Ticks - LastTicks) < 2310000)
            {
                if (SelectedClass != null)
                {
                    selectedText = true;
                    txtCity.Text = GetDisplyString(SelectedClass);// SelectedClass.CityName;
                }
                txtCity.Focus();
                HideTreeview();
                //PopupControl.IsOpen = false;
            }
            LastTicks = DateTime.Now.Ticks;
            //if (tv != null)
            //    tv.Focus();
        }

        private void tvData_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckFocus();
        }

        void CheckFocus()
        {

            DependencyObject dp = ((DependencyObject)System.Windows.Input.FocusManager.GetFocusedElement(this));
            if (dp != null)
            {
                if (((Control)dp).Name == "txtCity" || dp.GetType().Name == "SilverlightTreeViewItem" || dp.GetType().Name == "SilverlightTreeView")
                {
                }
                else
                {
                    HideTreeview();
                }
            }
            else
            {
                HideTreeview();
            }
        }

        void GoToItem()
        {
            //PopupControl.HorizontalOffset = 31;
            //PopupControl.VerticalOffset = 49;
            PopupControl.IsOpen = true;
            //ReturnConditions(txtCity.Text);
        }

        //private void ReturnConditions(string val)
        //{
        //    IList Model = ItemsSource as IList;

        //    selectedTV = null;
        //    for (int i = 0; i < Model.Count; i++)
        //    {
        //        if (GetDisplyString( Model.[i]).StartsWith(val, StringComparison.OrdinalIgnoreCase))
        //        {
        //            selectedTV = Model[i];
        //            ExpandAllParents(Model[i]);
        //        }
        //        else if (Model.GetCurrentData()[i].SubClass != null)
        //        {
        //            ReturnChildconditionsRecursively(Model.GetCurrentData()[i].SubClass, val);
        //        }
        //    }
        //    if (selectedTV == null)
        //    {
        //        HideTreeview();
        //    }
        //}

        //private void ReturnChildconditionsRecursively(ObservableCollection<HierarchicalCity> lst, string val)
        //{
        //    for (int j = 0; j < lst.Count; j++)
        //    {
        //        if (lst[j].CityName.StartsWith(val, StringComparison.OrdinalIgnoreCase))
        //        {
        //            selectedTV = lst[j];
        //            ExpandAllParents(lst[j]);
        //            break;
        //        }
        //        else if (lst[j].SubClass != null)
        //        {
        //            ReturnChildconditionsRecursively(lst[j].SubClass, val);
        //        }
        //    }

        //}

        //private void ExpandAllParents(HierarchicalCity t)
        //{
        //    SelectedClass = t;
        //    foreach (HierarchicalCity item in tvData.Items)
        //    {
        //        if (item.ExpandSuperclasses(t))
        //        {
        //            t.IsSelected = true;
        //            break;
        //        }
        //    }

        //}
        #endregion

        private void HideTreeview()
        {
            PopupControl.IsOpen = false;
            tv = null;
            SelectedClass = null;
            //foreach (HierarchicalCity item in tvData.Items)
            //{
            //    item.CollapseAll();
            //}
        }

        private string GetDisplyString(object item)
        {
            PropertyInfo prop = item.GetType().GetProperties().FirstOrDefault(x => x.Name == DisplayMemberPath);
            if (prop != null)
                return prop.GetValue(item).ToString();

            return string.Empty;
        }

        #region Textbox Events

        private void txtCity_GotFocus(object sender, RoutedEventArgs e)
        {
            IsTextboxFocus = true;
        }

        private void txtCity_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckFocus();
            IsTextboxFocus = false;
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (txtCity.Text == "")
            {
                HideTreeview();
            }
            else if (selectedText == false)
            {
                GoToItem();
            }
        }

        private void txtCity_KeyUp(object sender, KeyEventArgs e)
        {

            if (e.Key == Key.Enter && SelectedClass != null)
            {
                txtCity.Text = GetDisplyString(SelectedClass);
                selectedText = true;
                HideTreeview();
            }
            else if ((e.Key == Key.Down || e.Key == Key.Up) && tv != null)
            {
                tv.Focus();
            }
            else if (e.Key == Key.Escape)
            {
                HideTreeview();
            }
        }

        private void txtCity_KeyDown(object sender, KeyEventArgs e)
        {
            selectedText = false;
        }

        #endregion
    }

    public static class TreeViewExtensions
    {
        public static TreeViewItem ContainerFromItem(this TreeView treeView, object item)
        {
            TreeViewItem containerThatMightContainItem = (TreeViewItem)treeView.ItemContainerGenerator.ContainerFromItem(item);
            if (containerThatMightContainItem != null)
                return containerThatMightContainItem;
            else
                return ContainerFromItem(treeView.ItemContainerGenerator, treeView.Items, item);
        }

        private static TreeViewItem ContainerFromItem(ItemContainerGenerator parentItemContainerGenerator, ItemCollection itemCollection, object item)
        {
            foreach (object curChildItem in itemCollection)
            {
                TreeViewItem parentContainer = (TreeViewItem)parentItemContainerGenerator.ContainerFromItem(curChildItem);
                if (parentContainer == null)
                    return null;
                TreeViewItem containerThatMightContainItem = (TreeViewItem)parentContainer.ItemContainerGenerator.ContainerFromItem(item);
                if (containerThatMightContainItem != null)
                    return containerThatMightContainItem;
                TreeViewItem recursionResult = ContainerFromItem(parentContainer.ItemContainerGenerator, parentContainer.Items, item);
                if (recursionResult != null)
                    return recursionResult;
            }
            return null;
        }

        public static object ItemFromContainer(this TreeView treeView, TreeViewItem container)
        {
            TreeViewItem itemThatMightBelongToContainer = (TreeViewItem)treeView.ItemContainerGenerator.ItemFromContainer(container);
            if (itemThatMightBelongToContainer != null)
                return itemThatMightBelongToContainer;
            else
                return ItemFromContainer(treeView.ItemContainerGenerator, treeView.Items, container);
        }

        private static object ItemFromContainer(ItemContainerGenerator parentItemContainerGenerator, ItemCollection itemCollection, TreeViewItem container)
        {
            foreach (object curChildItem in itemCollection)
            {
                TreeViewItem parentContainer = (TreeViewItem)parentItemContainerGenerator.ContainerFromItem(curChildItem);
                if (parentContainer == null)
                    return null;
                TreeViewItem itemThatMightBelongToContainer = (TreeViewItem)parentContainer.ItemContainerGenerator.ItemFromContainer(container);
                if (itemThatMightBelongToContainer != null)
                    return itemThatMightBelongToContainer;
                TreeViewItem recursionResult = ItemFromContainer(parentContainer.ItemContainerGenerator, parentContainer.Items, container) as TreeViewItem;
                if (recursionResult != null)
                    return recursionResult;
            }
            return null;
        }
    }
}
